package com.asfo.demo.service.impl;

import com.asfo.demo.service.IFlowService;
import com.asfo.demo.comm.MDA;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class FlowServiceImpl implements IFlowService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ProcessEngineConfiguration processEngine;

    @Autowired
    private  HistoryService historyService;

    @Autowired
    private TaskService taskService;

    @Override
    public Deployment createFlow(String bpmName) {
        String bpmPath= MDA.BMP_CLASSPATH.join(File.separator).join(bpmName);
        InputStream inputStream = this.getClass().getResourceAsStream(bpmPath);
        Deployment expenseProcess = repositoryService.createDeployment().name("bpmName").addInputStream("bpmName", inputStream).deploy();


        return expenseProcess;
    }

    @Override
    public ProcessInstance startFlow(String processKey, Map<String, Object> paras) {
        return runtimeService.startProcessInstanceByKey(processKey,paras);
    }

    public boolean isFinished(String processInstanceId) {

        return historyService.createHistoricProcessInstanceQuery().finished()
                .processInstanceId(processInstanceId).count() > 0;
    }
    @Override
    public void genProcessDiagram(HttpServletResponse response, String processId) {
        //获得当前的活动节点
        String processDefinitionId="";
        if (this.isFinished(processId)) {// 如果流程已经结束，则得到结束节点
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();

            processDefinitionId=pi.getProcessDefinitionId();
        } else {// 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId=pi.getProcessDefinitionId();
        }




        //活动流程所有的历史获得节点
        List<String> highLightedActivitis = new ArrayList<String>();
        /**
         * 获得活动的节点
         */
        List<HistoricActivityInstance> highLightedActivitList =  historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();

        for(HistoricActivityInstance tempActivity : highLightedActivitList){
            String activityId = tempActivity.getActivityId();
            highLightedActivitis.add(activityId);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        List<String> flows=new ArrayList<>();
        InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, flows, processEngineConfiguration.getActivityFontName(),
                processEngineConfiguration.getLabelFontName(), processEngineConfiguration.getAnnotationFontName(), processEngineConfiguration.getClassLoader(),
                1.0, true);

        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = response.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } catch (IOException e) {
            log.error("操作异常",e);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }

    }


    @Override
    public boolean completeFlow(String taskId, Map params) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task==null)return false;
        taskService.complete(taskId,params);
        return true;
    }
}
